package org.pt.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.pt.components.Response;

import org.pt.dto.CreateWorkDto;
import org.pt.dto.UserFavoriteTag;
import org.pt.exception.DBNotFoundExcepton;
import org.pt.exception.PurchaseException;
import org.pt.exception.TorrentReceiveException;
import org.pt.exception.WorkException;
import org.pt.model.Tag;
import org.pt.model.UserPossess;
import org.pt.model.Work;
import org.pt.service.impl.UserServiceImpl;
import org.pt.service.impl.WorkServiceImpl;
import org.pt.utils.JwtToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.util.List;
import java.util.Locale;

import static org.pt.components.MsgEnum.AUTH_ERROR;

@Slf4j
@RestController
@RequestMapping("/work")
public class WorkController {
    @Autowired
    private UserServiceImpl userServiceImpl;
    @Autowired
    private WorkServiceImpl workServiceImpl;

    @GetMapping("announce")
    public Response<String> announce(String info_hash, String passkey, String event, String ip, int port, long uploaded, long downloaded) {
        System.out.println("announce");
        System.out.println(info_hash);
        System.out.println(passkey);
        System.out.println(event);
        System.out.println(ip);
        System.out.println(port);
        System.out.println(uploaded);
        System.out.println(downloaded);
        info_hash = info_hash.toLowerCase(Locale.ENGLISH);

        boolean result = workServiceImpl.announce(info_hash, passkey, event, ip, port, uploaded, downloaded);

        if (result)
            return Response.success("recieved");
        return Response.error(AUTH_ERROR.getMessage(), AUTH_ERROR.getCode());
    }

    @PostMapping("test")
    public Response<String> test() {
        return Response.success("hello word");
    }

    @Operation(
            summary = "创建作品",
            description = "用于用户作品信息，封面，.torrent文件"
    )
    @Parameters({
            @Parameter(
                    name = "metadata",
                    description = "作品信息，里面有一项花费信息这个别让用户自己定了，统一规定50魔力值",
                    required = true,
                    content = @Content(
                            mediaType = MediaType.APPLICATION_JSON_VALUE,
                            schema = @Schema(implementation = CreateWorkDto.class)
                    )
            ),
            @Parameter(
                    name = "cover",
                    description = "作品封面文件，只能是图片文件",
                    schema = @Schema(type = "string", format = "binary")
            ),
            @Parameter(
                    name = "torrent",
                    description = "作品文件,只能是.torrent",
                    schema = @Schema(type = "string", format = "binary")
            ),
            @Parameter(
                    name = "Authorization",
                    description = "认证token",
                    required = true,
                    in = ParameterIn.HEADER,
                    example = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
            )
    })
    @ApiResponses({
            @ApiResponse(
                    responseCode = "200",
                    description = "成功获取头像",
                    content = @Content(
                            mediaType = MediaType.APPLICATION_JSON_VALUE,
                            schema = @Schema(implementation = Response.class)
                    ))
    })
    @PostMapping(value = "createWork", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public Response<Work> createWork(@RequestHeader("Authorization") String token,
                                     @RequestPart("metadata") CreateWorkDto createWorkDto,
                                     @RequestPart("torrent") MultipartFile torrent,
                                     @RequestPart("cover") MultipartFile cover) throws WorkException, IOException {

        Integer id = JwtToken.getId(token);

        //cover应该允许为空
        return workServiceImpl.CreateTable(createWorkDto, id, cover, torrent);
    }

    @Operation(
            summary = "获取标签",
            description = "获取标签用于索引"
    )
    //获取热门标签
    @GetMapping(value = "getHottestTags")
    public Response<List<Tag>> getHottestTags() {
        return workServiceImpl.getTopTags(10);
    }

    @PostMapping("setWorkCost")
    public Response<String> setWorkCost(@RequestHeader("Authorization") String token,
                                        @RequestParam Integer workId,
                                        @RequestParam Integer newCost) throws WorkException, DBNotFoundExcepton {
        Integer userId = JwtToken.getId(token);
        return workServiceImpl.setWorkCostByOwner(userId, workId, newCost);
    }

    @Operation(
            summary = "购买",
            description = "购买作品，魔力值不够status为0，具体见报错信息"
    )
    @Parameters({
            @Parameter(
                    name = "workId",
                    description = "作品id",
                    schema = @Schema(type = "int")
            ),
            @Parameter(
                    name = "Authorization",
                    description = "认证token",
                    required = true,
                    in = ParameterIn.HEADER,
                    example = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
            )
    })
    @ApiResponses({
            @ApiResponse(
                    responseCode = "200",
                    description = "购买成功",
                    content = @Content(
                            mediaType = MediaType.APPLICATION_JSON_VALUE,
                            schema = @Schema(implementation = Response.class)
                    ))
    })
    @PostMapping(value = "purchaseWork")
    public Response<UserPossess> purchaseWork(@RequestHeader("Authorization") String token,
                                              @RequestParam Integer workId
    ) throws DBNotFoundExcepton, PurchaseException {
        Integer userId = JwtToken.getId(token);
        return workServiceImpl.WorkPurchase(userId, workId);
    }

    @Operation(
            summary = "下载文件",
            description = "下载种子文件"
    )
    @Parameters({
            @Parameter(
                    name = "workId",
                    description = "作品id",
                    schema = @Schema(type = "int")
            ),
            @Parameter(
                    name = "Authorization",
                    description = "认证token",
                    required = true,
                    in = ParameterIn.HEADER,
                    example = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
            )
    })
    @ApiResponses({
            @ApiResponse(
                    responseCode = "200",
                    description = "下载成功",
                    content = @Content(
                            mediaType = MediaType.APPLICATION_JSON_VALUE,
                            schema = @Schema(implementation = Response.class)
                    ))
    })
    @PostMapping(value = "getWorkTorrent")
    public Response<String> getWorkTorrent(@RequestHeader("Authorization") String token,
                                           @RequestParam Integer workId,
                                           HttpServletResponse response) throws DBNotFoundExcepton, PurchaseException, TorrentReceiveException, IOException {
        Integer userId = JwtToken.getId(token);
        ByteArrayResource newTorrent = workServiceImpl.getWorkTorrent(userId, workId);

        response.setContentType("application/x-bittorrent");
        response.setHeader("Content-Disposition",
                "attachment; filename*=UTF-8''" + newTorrent.getFilename());

        try (OutputStream os = response.getOutputStream()) {
            StreamUtils.copy(newTorrent.getInputStream(), os);
        }
        return Response.success("传输中");
    }

    @Operation(
            summary = "删除作品",
            description = "删除作品信息和文件"
    )
    @Parameters({
            @Parameter(
                    name = "workId",
                    description = "作品id",
                    schema = @Schema(type = "int")
            ),
            @Parameter(
                    name = "Authorization",
                    description = "认证token",
                    required = true,
                    in = ParameterIn.HEADER,
                    example = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
            )
    })
    @PostMapping(value = "deleteWork")
    public Response<String> deleteWork(@RequestHeader("Authorization") String token,
                                       @RequestParam Integer workId
    ) throws WorkException, DBNotFoundExcepton {
        Integer id = JwtToken.getId(token);

        return workServiceImpl.userDeleteWork(id, workId);
    }

    @Operation(
            summary = "获取用户拥有的作品",
            description = "包括购买和创建的"
    )
    @Parameters({
            @Parameter(
                    name = "Authorization",
                    description = "认证token",
                    required = true,
                    in = ParameterIn.HEADER,
                    example = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
            )
    })
    @GetMapping(value = "get_possess_work")
    public Response<List<Work>> getPossessWork(@RequestHeader("Authorization") String token) {
        Integer id = JwtToken.getId(token);
        return workServiceImpl.getPossessWork(id);
    }

    @Operation(
            summary = "获取用户创建的作品"
    )
    @Parameters({
            @Parameter(
                    name = "Authorization",
                    description = "认证token",
                    required = true,
                    in = ParameterIn.HEADER,
                    example = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
            )
    })
    @GetMapping(value = "get_user_create_work")
    public Response<List<Work>> getUserCreatedWork(@RequestHeader("Authorization") String token) {
        Integer id = JwtToken.getId(token);
        return workServiceImpl.getUserCreatedWork(id);
    }

    @Operation(
            summary = "获取用户购买的作品"
    )
    @Parameters({
            @Parameter(
                    name = "Authorization",
                    description = "认证token",
                    required = true,
                    in = ParameterIn.HEADER,
                    example = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
            )
    })
    @GetMapping(value = "get_user_purchase_work")
    public Response<List<Work>> getUserPurchasedWork(@RequestHeader("Authorization") String token) {
        Integer id = JwtToken.getId(token);
        return workServiceImpl.getUserPurchasedWork(id);
    }

    @Operation(
            summary = "通过标签获取作品列表"
    )
    @PostMapping(value = "search_by_tags")
    public Response<List<Work>> searchByTags(@RequestBody List<String> Tags) {

        return workServiceImpl.searchByTags(Tags);
    }

    @GetMapping(value = "search_by_name")
    public Response<List<Work>> getByName(@RequestParam("name") String name) {
        return workServiceImpl.searchByName(name);
    }

    /**
     * 返回用户最喜好的几个tags
     *
     * @param token
     * @param tagsNum 返回几个
     * @return
     */
    @GetMapping(value = "get_favorite_tags")
    public Response<List<UserFavoriteTag>> getFavoriteTags(@RequestHeader("Authorization") String token,
                                                           @RequestParam Integer userId,
                                                           @RequestParam Integer tagsNum) {
        return workServiceImpl.getFavoriteTags(userId, tagsNum);
    }

    @GetMapping(value = "get_works")
    public Response<Page<Work>> getWorks(@RequestHeader("Authorization") String token,
                                         @RequestParam String orderBy,
                                         @RequestParam int pageNum,
                                         @RequestParam int pageSize) throws Exception {
        return workServiceImpl.getWorksPageByUser(orderBy, pageNum, pageSize);
    }
    @GetMapping(value = "get_works_with_tags")
    public Response<Page<Work>> getWorks2(@RequestHeader("Authorization") String token,
                                         @RequestParam List<String> tags,
                                         @RequestParam String orderBy,
                                         @RequestParam int pageNum,
                                         @RequestParam int pageSize) throws Exception {
        return workServiceImpl.getWorksPageByUserWithTags(tags,orderBy, pageNum, pageSize);
    }

    /**
     * 获取当前运行中版本
     */
    @GetMapping(value = "version")
    public Response<String> getVersion() {
        return Response.success("2025/6/12 2:17");
    }

    @GetMapping("getCover")
    public ResponseEntity<byte[]> getCover(@RequestParam String coverPath) throws IOException {
        if(coverPath==null || coverPath.isEmpty())
        {
            coverPath="cover/default.png";
        }
        File file = new File(coverPath);
        byte[] imageBytes = Files.readAllBytes(file.toPath());
        // 构建 HTTP 响应头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.IMAGE_JPEG);
        headers.setContentLength(imageBytes.length);
        // 返回包含图片字节数组的 ResponseEntity
        return new ResponseEntity<>(imageBytes, headers, HttpStatus.OK);
    }

    @GetMapping(value = "getWorkTag")
    public Response<List<String>> getWorkTag(@RequestParam int workId) {
        return workServiceImpl.getWorkTags(workId);
    }
}
